
//----------------------------------------------------------------------------
// Copyright (c) 2011 Texas Instruments, Inc.
// This is an unpublished work created in the year stated above.
// Texas Instruments owns all rights in and to this work and
// intends to maintain and protect it as an unpublished copyright.
// In the event of either inadvertent or deliberate publication,
// the above stated date shall be treated as the year of first
// publication. In the event of such publication, Texas Instruments
// intends to enforce its rights in the work under the copyright
// laws as a published work.
//----------------------------------------------------------------------------
// Filename                : DRV922XX.h
//
// Functional Description  : DRV922XX public interface
//
// Creation Date           : 2-Feb-2011
//
//----------------------------------------------------------------------------

#ifndef DRV922XX_H_
#define DRV922XX_H_

#include "MSP430DRC4300.h"
#include "DRV8620.h"

#define MONTEREY_ROM	// Uncomment to enable support for Monterey-ROM		

#ifdef MONTEREY_ROM

#define USCI_CTL0_REG	UCB0CTL0
#define USCI_CTL1_REG	UCB0CTL1
#define USCI_TXBUF_REG	UCB0TXBUF
#define USCI_RXBUF_REG	UCB0RXBUF

#else	// Monterey-FROM/FRAM

#define USCI_CTL0_REG	UCA0CTL0
#define USCI_CTL1_REG	UCA0CTL1
#define USCI_TXBUF_REG	UCA0TXBUF
#define USCI_RXBUF_REG	UCA0RXBUF

#endif

/*!
  \file "DRV922XX.h"
  \brief Definitions and function prototypes for the DRV941XX family of E-Bike controllers
 */
 
/*! \def ADC_CHANNEL_SPEEDIN
    \brief This the ADC channel that is used for the throttle voltage when calling any of the ADC functions
 */
#define ADC_CHANNEL_SPEEDIN   8

/*! \def ADC_CHANNEL_CURRENT
    \brief This is the ADC channel that is used for reading current
 */
#define ADC_CHANNEL_CURRENT   14

/*! \def ADC_CHANNEL_TEMPERATURE
    \brief This is the ADC channel that is used for reading temperature
 */
#define ADC_CHANNEL_TEMPERATURE		15


/*!
  \fn void drv922xxSpiInit()
  \brief Initializes the DRV941XX SPI interface for communication with the AFE and releases
  it from reset
 */
static inline void drv922xxSpiInit()
{
	USCI_CTL1_REG |= UCSWRST;								// Hold the peripheral in reset
	USCI_CTL1_REG = UCSSEL__ACLK | UCSWRST;					// Put in reset first
    USCI_CTL0_REG = UCCKPH | UCMSB | UCMST | UCSYNC; 		// 3-pin, 8-bit SPI master, MSB first, data sample/setup, clock active high, sync (set for SPI)
    USCI_CTL1_REG &= ~UCSWRST;								// Release from reset
}    
	

/*!
  \fn static inline void drv922xxSpiWrite(unsigned char addr, unsigned char data)
  \brief Writes one byte of data to the given register address on the AFE using SPI.
 */
static inline void drv922xxSpiWrite(unsigned char addr, unsigned char data)
{
	USCI_TXBUF_REG = addr;
	__delay_cycles(2);
    
    USCI_TXBUF_REG = data;
    __delay_cycles(10);
}

/*!
  \fn static inline unsigned char drv922xxSpiRead(unsigned char addr)
  \brief Reads 8b of data from the AFE at the given register address using SPI.
 */
static inline unsigned char drv922xxSpiRead(unsigned char addr)
{
	USCI_TXBUF_REG = addr;
	__delay_cycles(2);
	
    USCI_TXBUF_REG = 0;
	__delay_cycles(10);
	
    return USCI_RXBUF_REG;
}

/*!
  \fn static inline void drc922xxAdcStartAndDelay(unsigned char channel)
  \brief Starts and ADC conversion of the given channel. 
  \param channel ADC channel to convert
 */
static inline void drv922xxAdcStartAndDelay(unsigned char channel)
{
	drv922xxSpiWrite(SPI_ADC1_WRITE, ((channel << 4) | ADC_START)); // | ISNS_HIGAIN));		// Set channel, high gain (for iReads) and start
	__delay_cycles(10);																	// 420 ns of delay
}


/*!
  \fn static inline unsigned int drv922xxAdcRead(unsigned char channel)
  \brief This function starts a conversion of the given channel and returns the 10b result
  \param channel ADC channel to convert
 */
static inline unsigned int drv922xxAdcRead(unsigned char channel)
{
	unsigned short adc_value;
	
	drv922xxAdcStartAndDelay(channel);
	adc_value = (drv922xxSpiRead(SPI_ADC1_READ) & 0x3) << 8;
    adc_value |= drv922xxSpiRead(SPI_ADC2_READ);
    
    return(adc_value);
}

/*!
  \fn static inline unsigned int drv922xxAdcReadCurrent()
  \brief Starts an ADC conversion of the current and returns
  
  This non-blocking function sets the ADC MUX to the current channel and starts an ADC read, then returns. 
 */
static inline unsigned int drv922xxAdcReadCurrent()
{
	unsigned int adc_value;
	
	// Start voltage conversion
	drv922xxSpiWrite(SPI_ADC1_WRITE, (ADC_START | (ADC_CHANNEL_CURRENT << 4)));
	__delay_cycles(10);		
	
	adc_value = (drv922xxSpiRead(SPI_ADC1_READ) & 0x3) << 8;
    adc_value |= drv922xxSpiRead(SPI_ADC2_READ);
    
    return(adc_value);
}
/*!
  \fn static inline unsigned int drv922xxAdcReadTemperature()
  \brief Starts an ADC conversion of the temperature and returns
  
  This non-blocking function sets the ADC MUX to the temperature channel and starts an ADC read, then returns. 
 */
static inline unsigned int drv922xxAdcReadTemperature()
{
	unsigned int adc_value;
	
	// Start voltage conversion
	drv922xxSpiWrite(SPI_ADC1_WRITE, (ADC_START | (ADC_CHANNEL_TEMPERATURE << 4)));
	__delay_cycles(10);		
	
	adc_value = (drv922xxSpiRead(SPI_ADC1_READ) & 0x3) << 8;
    adc_value |= drv922xxSpiRead(SPI_ADC2_READ);
    
    return(adc_value);
}
/*!
  \fn static inline void drv922xxSpiResetAfeSpi()
  \brief Holds the AFE SPI slave in reset
 */
static inline void drv922xxSpiResetAfeSpi() { P3OUT |= BIT7; }

/*!
  \fn static inline void drv922xxSpiReleaseAfeSpi()
  \brief Releases the AFE SPI slave from reset, so that it can begin accepting characters
 */
static inline void drv922xxSpiReleaseAfeSpi() { P3OUT &= ~BIT7; }

#endif /*DRV922XX_H_*/
